package Day_0226.ProxyPattern;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author zxc
 * @date 2023/02/26 21:49
 **/
public class JDKDynamicProxy {
    public static void main(String[] args) {
        /**
         * 谈一谈对于JDK动态代理的理解
         * ===》
         * 1.JDK动态代理的概念
         * （1）动态代理也叫做，JDK代理、接口代理。
         * （2）动态代理的对象，是利用JDK的API，动态地在内存中构建代理对象
         * （是根据被代理的接口，来动态生成代理类的class文件，并加载运行的过程），
         * ===》 这就叫动态代理;
         *
         * ===》
         * 总结 ：
         * （1）JDK动态代理，会在运行时,动态地在内存中构建代理对象;
         * （2）JDK动态代理，是面向接口的，所需要进行代理的目标业务类对象是 必然要实现该接口的;
         *
         * 2.JDK动态代理的优缺点
         * （1）缺点 ：必须是面向接口，目标业务类必须实现接口;
         * （2）优点 ：不用关心代理类，只需要在运行阶段，才指定代理哪一个对象;
         *
         */
    }
}
// 接口
interface UserDao1 {
    void save();
}
// 接口实现类（目标业务类）
class UserDaoImpl implements UserDao1 {
    public void save() {
        System.out.println("保存数据方法");
    }
}
// 每次生成动态代理类对象时,实现了InvocationHandler接口的调用处理器对象
class InvocationHandlerImpl implements InvocationHandler {
    // 根据业务实现类对象，用来调用具体的业务方法
    private Object target;
    // 通过构造函数，传入目标对象
    public InvocationHandlerImpl(Object target) {
        this.target = target;
    }
    //动态代理实际运行的代理方法---invoke方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("调用开始处理1...");
        // invoke()方法是以反射的方式来创建对象，
        // 第一个参数是要创建的对象，第二个是构成方法的参数，由第二个参数来决定创建对象使用哪个构造方法
        Object result = method.invoke(target, args);
        System.out.println("调用结束处理1...");
        return result;
    }
}
class Test1 {
    public static void main(String[] args) {
        // 1.所需要被代理的目标对象;
        UserDao1 userDaoImpl = new UserDaoImpl();

        // 2.获取 调用处理动态代理的实例;
        InvocationHandlerImpl invocationHandlerImpl = new InvocationHandlerImpl(userDaoImpl);
        // 3.获取目标代理对象的类加载器;
        ClassLoader loader = userDaoImpl.getClass().getClassLoader();
        // 4.获取目标代理对象所继承的接口;
        Class<?>[] interfaces = userDaoImpl.getClass().getInterfaces();

        // 主要装载器、一组接口及调用处理动态代理实例;
        UserDao1 newProxyInstance = (UserDao1) Proxy.newProxyInstance(loader, interfaces, invocationHandlerImpl);
        newProxyInstance.save();
    }
}
